﻿// <copyright file="IMod.cs" company="SingularityShift">
// Copyright (c) 2009 SingularityShift.com
// </copyright>
// <author>Ben McClure</author>
// <email>ben@singularityshift.com</email>
// <date>2009-08-14</date>
// <summary>A public interface which defines an object representing a mod for a game</summary>
namespace GameLib.Games
{
    using System;
    using System.Collections.Generic;

    using GameLib.Games.CompositeModel;
    using GameLib.Games.Util;

    /// <summary>
    /// Represents a mod for a game in the GameLib.
    /// </summary>
    public interface IMod : IGameComponent
    {
        /// <summary>
        /// Thrown when anything about a mod is changed
        /// </summary>
        event EventHandler<ModChangedEventArgs> ModChanged;

        /// <summary>
        /// Gets the IGame that owns (is the parent of) this mod.
        /// </summary>
        IClient Owner
        {
            get;
        }

        /// <summary>
        /// <para>Gets or sets the unique identifier describing the mod. Often, this is just the mod's filename.</para>
        /// <para>The format of the Id is usually specified by the game the mod is for.</para>
        /// </summary>
        string Id
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets a human-readable title for the mod. When not provided, usually GameLib generates one based on the FileName.
        /// </summary>
        string Name
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the full path (or relative path to the game's ModDir) to this mod in the filesystem.
        /// </summary>
        string File
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets a URI pointing to more information about the mod (usually a homepage URL)
        /// </summary>
        System.Uri Uri
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets a value indicating whether this mod is recognized by the application in a way defined by the application
        /// </summary>
        bool Recognized
        {
            get;
            set;
        }

        /// <summary>
        /// <para>Gets or sets a value indicating whether this mod is considered obsolete.</para>
        /// <para>Null values can be considered NOT obsolete, to avoid the overhead of always having to set this value when it's usually unused.</para>
        /// </summary>
        bool Obsolete
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the type of this mod as a type string defined by the application
        /// </summary>
        string Type
        {
            get;
            set;
        }

        /// <summary>
        /// <para>Gets or sets a value indicating whether this mod is considered outdated.</para>
        /// <para>This should be set it:
        /// - This is a known older version of the mod than the current version (or than any other version in the current ModList usually)
        /// - There is something else that should replace this (add a Message about it)
        /// - This is no longer working in the latest stable version of the game</para>
        /// </summary>
        bool Outdated
        {
            get;
            set;
        }

        /// <summary>
        /// <para>Gets or sets a value indicating whether this mod is invariably required to be active in this mod list.</para>
        /// <para>Set this value to true if:
        /// - Other mods depend on this mod which are also required (or cannot be deactivated for any reason)
        /// - This mod is required for the game to operate
        /// - This mod is required for the implementing class's uses</para>
        /// </summary>
        bool Required
        {
            get;
            set;
        }

        /// <summary>
        /// Generally a short text describing what the mod does
        /// </summary>
        string Description
        {
            get;
            set;
        }

        /// <summary>
        /// Any notes for the user that don't warrant the important of a Message
        /// </summary>
        string Notes
        {
            get;
            set;
        }

        /// <summary>
        /// Gets a ModState enumeration defining whether (in this order) it has any conflicts, dependencies, or messages (or nothing).
        /// </summary>
        ModStates State
        {
            get;
        }

        /// <summary>
        /// Gets a collection of potential or known conflicts with this mod.
        /// </summary>
        IList<IModConflict> Conflicts
        {
            get;
        }

        /// <summary>
        /// Gets a collection of dependencies for this mod.
        /// </summary>
        IList<IModDependency> Dependencies
        {
            get;
        }

        /// <summary>
        /// Gets a collection of messages regarding this mod.
        /// </summary>
        IList<IModMessage> Messages
        {
            get;
        }

        /// <summary>
        /// Gets or sets a value indicating whether this mod is currently active in its owner IGame.
        /// </summary>
        bool IsActive
        {
            get;
            set;
        }

        /// <summary>
        /// Determines the state of the mod based on its conflicts, dependencies, messages and status.
        /// </summary>
        /// <typeparam name="T">The type of IMod object this should be assumed to be</typeparam>
        /// <returns>A ModState value indicating the current state of the mod</returns>
        ModStates GetState<T>() where T : IMod;

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Sets an owner. </summary>
        ///
        /// <param name="game"> The game. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        void SetOwner(IClient game);

        /// <summary>
        /// Adds an IModConflict to the game's list of known conflicts.
        /// </summary>
        /// <param name="conflict">The IModConflict object to add to the list of known conflicts.</param>
        void AddConflict(IModConflict conflict);

        /// <summary>
        /// Adds an IModDependency to the game's list of known dependencies.
        /// </summary>
        /// <param name="dependency">The IModDependency object to add to the list of known dependencies.</param>
        void AddDependency(IModDependency dependency);

        /// <summary>
        /// Adds an IModMessage to the game's list of known dependencies.
        /// </summary>
        /// <param name="message">The IModMessage object to add to the list of messages about this mod.</param>
        void AddMessage(IModMessage message);

        /// <summary>
        /// Returns a generic list of IModConflict items from this mod that match one or more mods in the provided IModList.
        /// </summary>
        /// <param name="modList">The IModList object to check for conflicts against.</param>
        /// <returns>A collection of IModConflict objects which match the provided IModList</returns>
        IList<IModConflict> FindConflictsWithMatches<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// Returns a generic list of IModConflict items from this mod that match the provided mod
        /// </summary>
        /// <param name="mod">The IMod object to check for conflicts against.</param>
        /// <returns>A collection of IModConflict objects which match the provided IModList</returns>
        IList<IModConflict> FindConflictsWithMatches<T>(T mod) where T : IMod;

        /// <summary>
        /// Returns a generic list of IModDependency items from this mod that are missing from the provided IModList.
        /// </summary>
        /// <param name="modList">The IModList object to check for dependencies against.</param>
        /// <returns>A collection of IModDependency objects which don't match the provided IModList</returns>
        IList<IModDependency> FindDependenciesWithoutMatches<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// Returns a generic list of IModMessage items from this mod that match the provided IModList.
        /// </summary>
        /// <param name="modList">The IModList object to check for matching messages against.</param>
        /// <returns>A collection of IModMessage objects which match the provided IModList</returns>
        IList<IModMessage> FindMessagesWithMatches<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// Returns a generic list of IMod objects from the provided IModList which match any of this mod's Conflicts.
        /// </summary>
        /// <param name="modList">The collection of mods to check for conflicts in</param>
        /// <returns>A collection of IMod objects which match this mod's Conflicts</returns>
        IModCollection<T> FindMatchingConflicts<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// Returns a list of IMods from the provided IModList which match any of this mod's Messages.
        /// </summary>
        /// <param name="modList">The collection of mods to check for messages against.</param>
        /// <returns>A collection of IMod objects from the provided IModList which match this mod's Messages</returns>
        IModCollection<T> FindMatchingMessages<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// Returns a list of IMods from the provided IModList which match any of this mod's Dependencies.
        /// </summary>
        /// <param name="modList">The collection of mods to check for dependencies against.</param>
        /// <returns>A collection of IMods from the provided IModList which match any of this mod's Dependencies</returns>
        IModCollection<T> FindMatchingDependencies<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// Returns a list of IModDependencies from this mod's Dependencies which are missing from the provided IModList.
        /// </summary>
        /// <param name="modList">The collection of mods to check for dependencies against.</param>
        /// <returns>A collection of IModDependencies from this mod which are missing from the provided IModList</returns>
        IList<IModDependency> FindMissingDependencies<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// <para>Determines whether this mod has any conflicts matching the provided IModList.</para>
        /// <para>Upon detection of the first matching conflict, this function returns true.</para>
        /// </summary>
        /// <param name="modList">The collection of mods to check for conflicts against.</param>
        /// <returns>A bool indicating whether or not this mod has any matching conflicts.</returns>
        bool HasMatchingConflicts<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// <para>Determines whether this mod has any messages matching the provided IModList.</para>
        /// <para>Upon detection of the first matching message, this function returns true.</para>
        /// </summary>
        /// <param name="modList">The collection of mods to check for messages against.</param>
        /// <returns>A bool indicating whether or not this mod has any matching messages.</returns>
        bool HasMatchingMessages<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// <para>Determines whether this mod has any dependencies matching the provided IModList.</para>
        /// <para>Upon detection of the first matching dependency, this function returns true.</para>
        /// </summary>
        /// <param name="modList">The collection of mods to check for dependencies against.</param>
        /// <returns>A bool indicating whether or not this mod has any matching dependencies.</returns>
        bool HasMatchingDependencies<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// <para>Determines whether this mod has any dependencies not found within the provided IModList.</para>
        /// <para>Upon detection of the first missing dependency, this function returns true.</para>
        /// </summary>
        /// <param name="modList">The collection of mods to check for missing dependencies against.</param>
        /// <returns>A bool indicating whether or not this mod has any missing dependencies.</returns>
        bool HasMissingDependencies<T>(IModCollection<T> modList) where T : IMod;

        /// <summary>
        /// Removes a conflict from this mod's Conflicts collection.
        /// </summary>
        /// <param name="index">The 0-based index of the conflict to remove.</param>
        void RemoveConflict(int index);

        /// <summary>
        /// Removes a conflict from this mod's Conflicts collection.
        /// </summary>
        /// <param name="conflict">The IModConflict object to remove.</param>
        void RemoveConflict(IModConflict conflict);

        /// <summary>
        /// Removes a dependency from this mod's Dependencies collection.
        /// </summary>
        /// <param name="index">The 0-based index of the dependency to remove.</param>
        void RemoveDependency(int index);

        /// <summary>
        /// Removes a dependency from this mod's Dependencies collection.
        /// </summary>
        /// <param name="dependency">The IModDependency object to remove.</param>
        void RemoveDependency(IModDependency dependency);

        /// <summary>
        /// Removes a message from this mod's Messages collection.
        /// </summary>
        /// <param name="index">The 0-based index of the message to remove.</param>
        void RemoveMessage(int index);

        /// <summary>
        /// Removes a message from this mod's Messages collection.
        /// </summary>
        /// <param name="message">The IModMessage object to remove.</param>
        void RemoveMessage(IModMessage message);
    }
}